﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
// std headers

// qt headers
#include <QScrollBar>

// gcmp headers

// custom headers
#include "CategoriesTreeView.h"
#include "ScrollbarStyles.h"
#include "CategoriesTreeModel.h"
#include "CustomTreeItem.h"
#include "IGmepGcsCategory.h"
#include "GbmpNew.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h" 

namespace gmepgcs
{
    CategoriesTreeView::CategoriesTreeView(QWidget *parent /*= nullptr*/) :
        QTreeView(parent)
    {
        Init();
    }

    CategoriesTreeView::~CategoriesTreeView()
    {

    }

    CategoriesTreeModel * CategoriesTreeView::Model()
    {
        return dynamic_cast<CategoriesTreeModel *>(model());
    }

    void CategoriesTreeView::SelectCategory(const std::wstring & categoryCode)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(Model(), L"Model()为空", L"GMEP", L"2024-01-30");
        auto index = Model()->FindIndex(categoryCode);
        if (!index.isValid())
        {
            return;
        }

        DBG_WARN_AND_RETURN_VOID_UNLESS(selectionModel(), L"selectionModel()为空", L"GMEP", L"2024-01-30");
        selectionModel()->select(index, { QItemSelectionModel::SelectionFlag::Select, QItemSelectionModel::SelectionFlag::Current });
    }

    void CategoriesTreeView::ExpandCategory(const std::wstring & categoryCode)
    {
        DBG_WARN_AND_RETURN_VOID_UNLESS(Model(), L"Model()为空", L"GMEP", L"2024-01-30");
        auto index = Model()->FindIndex(categoryCode);
        if (!index.isValid())
        {
            return;
        }

        setExpanded(index, true);
    }

    void CategoriesTreeView::ExpandCategories(const std::vector<std::wstring>& categoryCodes)
    {
        for (auto &categoryCode : categoryCodes)
        {
            ExpandCategory(categoryCode);
        }
    }

    std::vector<std::wstring> CategoriesTreeView::GetExpandedCategoryCodes()
    {
        std::vector<QModelIndex> expandedIndexes;
        auto expandedCategoryCodes = std::vector<std::wstring>();
        DBG_WARN_AND_RETURN_UNLESS(Model(), expandedCategoryCodes, L"Model()为空", L"GMEP", L"2024-01-30");
        Model()->FindIndexes([=](const QModelIndex idx) {return isExpanded(idx); }, expandedIndexes);
        
        for (auto &expandedIndex : expandedIndexes)
        {
            auto item = static_cast<CustomTreeItem*>(expandedIndex.internalPointer());
            if (!item)
            {
                continue;
            }

            auto itemData = item->Data(0).value<void*>();
            if (!itemData)
            {
                continue;
            }

            auto category = static_cast<IGmepGcsCategory *>(itemData);
            if (!category)
            {
                continue;
            }

            expandedCategoryCodes.push_back(category->Code);
        }

        return expandedCategoryCodes;
    }

    void CategoriesTreeView::Init()
    {
        // CategoriesTreeView self
        setFixedWidth(177);
        setStyleSheet(
            "QTreeView{"
            "border-top:1px solid rgb(210,215,220);"
            "border-right:1px solid rgb(210,215,220);"
            "}");
        setHeaderHidden(true);

        DBG_WARN_AND_RETURN_VOID_UNLESS(verticalScrollBar(), L"verticalScrollBar()为空", L"GMEP", L"2024-01-30");
        verticalScrollBar()->setStyleSheet(ScrollBarStyles::VerticalScrollBarStyle());
        setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);

        DBG_WARN_AND_RETURN_VOID_UNLESS(horizontalScrollBar(), L"horizontalScrollBar()为空", L"GMEP", L"2024-01-30");
        horizontalScrollBar()->setStyleSheet(ScrollBarStyles::HorizontalScrollBarStyle());
        setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOff);

        // model
        setModel(NEW_AS_QT(CategoriesTreeModel));

        // on item clicked
        connect(this, &QTreeView::clicked, [=](const QModelIndex &index) {
            if (!index.isValid())
            {
                emit CategoryClicked(nullptr);
                return;
            }

            CustomTreeItem *item = static_cast<CustomTreeItem*>(index.internalPointer());
            if (!item)
            {
                emit CategoryClicked(nullptr);
                return;
            }

            auto itemData = item->Data(index.column()).value<void*>();
            if (!itemData)
            {
                emit CategoryClicked(nullptr);
                return;
            }

            auto category = static_cast<IGmepGcsCategory*>(itemData);
            if (!category)
            {
                emit CategoryClicked(nullptr);
                return;
            }

            emit CategoryClicked(category);
        });
    }

}